You believe or you no believe, he dey possible to compute with encrypted data. Make I talk am another way sey he dey possible to run program where ALL of the variables in the program dey encrypted!
For this tutoria we go learn basic tools of encrypted computation. In particular, we go focus on one popular approach called Secure Multi-Party Computation. We go build encrypted calculator wey fit perform calculations on encrypted numbers for this lesson.
Person wey write am:
Reference wey you fit use:
Person wey translate am:
SMPC na strange form of "encryptioon". Instead make we use public/private key to encrypt a variable, we go split each value into multiple shares
, each of dem operates like a private key. Typically, we go distribute these shares
amongst 2 or more owners. Thus, to decrypt the variable, all owners must agree sey make we decryt am. In essence, everyone go get private key.
So, let's say we wan "encrypt" a variable x
, we fit do am in the following way.
So, let's say we wanted to "encrypt" a variable x
, we could do so in the following way.
Encryption no dey use floats or real numbers but he dey happen in a mathematical space called integer quotient ring wey be the integer wey dey between
0
andQ-1
, whereQ
na prime and "big enough" so that the space can contain all the numbers that we use in our experiments. In practice, given a valuex
integer, we dox % Q
to fit in the ring. (That's why we dey avoid to use numberx' > Q
).
In [1]:
Q = 1234567891011
In [2]:
x = 25
In [3]:
import random
def encrypt(x):
share_a = random.randint(-Q,Q)
share_b = random.randint(-Q,Q)
share_c = (x - share_a - share_b) % Q
return (share_a, share_b, share_c)
In [4]:
encrypt(x)
Out[4]:
In [5]:
def decrypt(*shares):
return sum(shares) % Q
In [6]:
a,b,c = encrypt(25)
In [7]:
decrypt(a, b, c)
Out[7]:
Importantly, notice sey if we try to decrypt with only two shares, the decryption no dey work!
In [8]:
decrypt(a, b)
Out[8]:
We go need all of the owners to participate if we wan decrypt value. Na like this shares
dey act like private keys, everytin must to dey before we go fit decrypt a value.
In [9]:
x = encrypt(25)
y = encrypt(5)
In [10]:
def add(x, y):
z = list()
# the first worker adds their shares together
z.append((x[0] + y[0]) % Q)
# the second worker adds their shares together
z.append((x[1] + y[1]) % Q)
# the third worker adds their shares together
z.append((x[2] + y[2]) % Q)
return z
In [11]:
decrypt(*add(x,y))
Out[11]:
And there you get am! If each worker (separately) add their shares togeda, the resulting shares go decrypt to the correct vallues (25 + 5 == 30).
As he dey so, SMPC protocols exist go allow make this encrypted computation fit do the following operations:
If we use these basic underlying primitives, we go fit perform arbitrary computation!!!
In the next section, we go learn how we fit use PySyft library to perform these operations!
In the previous sections, we talk about some intuition wey dey around SMPC if he go work. However, we no wan use hand write everi primitive operations ourselves when we fit write our encrypted programs. So, for this section we go studi the basics of how we go do encrypted computation using PySyft. Particularly, we go focus on how to do 3 primitives wey we mention before: addition, multiplication, and comparison.
First, we go first create few Virtual Worker (wey you don dey familiar as you don study our previous tutorials).
In [12]:
import torch
import syft as sy
hook = sy.TorchHook(torch)
bob = sy.VirtualWorker(hook, id="bob")
alice = sy.VirtualWorker(hook, id="alice")
bill = sy.VirtualWorker(hook, id="bill")
In [13]:
x = torch.tensor([25])
In [14]:
x
Out[14]:
In [15]:
encrypted_x = x.share(bob, alice, bill)
In [16]:
encrypted_x.get()
Out[16]:
In [17]:
bob._objects
Out[17]:
In [18]:
x = torch.tensor([25]).share(bob, alice, bill)
In [19]:
# Bob's share
bobs_share = list(bob._objects.values())[0]
bobs_share
Out[19]:
In [20]:
# Alice's share
alices_share = list(alice._objects.values())[0]
alices_share
Out[20]:
In [21]:
# Bill's share
bills_share = list(bill._objects.values())[0]
bills_share
Out[21]:
If we want, we fit decrypt these values if we use the SAME approach we don talk about before now!!!
In [22]:
Q = x.child.field
(bobs_share + alices_share + bills_share) % Q
Out[22]:
Look am wella, as we call .share()
he just split value into 3 shares ans he come send one share go each parties!
In [23]:
x = torch.tensor([25]).share(bob,alice)
y = torch.tensor([5]).share(bob,alice)
In [24]:
z = x + y
z.get()
Out[24]:
In [25]:
z = x - y
z.get()
Out[25]:
For multiplication we go need an additional party who go dey responsible to dey consistently generate random numbers (he no go collude with any other parties). We dey call this person "crypto provider". For all intensive purposes, the crypto provider na just additional VirtualWorker, but he go dey important to acknowledge sey crypto provider no be "owner" onto sey he/she no get him own shares but na someone wey we need to trust make he no go collude with ani existing shareholders.
In [26]:
crypto_provider = sy.VirtualWorker(hook, id="crypto_provider")
In [27]:
x = torch.tensor([25]).share(bob,alice, crypto_provider=crypto_provider)
y = torch.tensor([5]).share(bob,alice, crypto_provider=crypto_provider)
In [28]:
# multiplication
z = x * y
z.get()
Out[28]:
You fit do matrix multiplication
In [29]:
x = torch.tensor([[1, 2],[3,4]]).share(bob,alice, crypto_provider=crypto_provider)
y = torch.tensor([[2, 0],[0,2]]).share(bob,alice, crypto_provider=crypto_provider)
In [30]:
# matrix multiplication
z = x.mm(y)
z.get()
Out[30]:
He dey possible to private compare private values. We go rely on SecureNN protocol, we fit find the details here. The result of the comparison na private shared tensor.
In [31]:
x = torch.tensor([25]).share(bob,alice, crypto_provider=crypto_provider)
y = torch.tensor([5]).share(bob,alice, crypto_provider=crypto_provider)
In [32]:
z = x > y
z.get()
Out[32]:
In [33]:
z = x <= y
z.get()
Out[33]:
In [34]:
z = x == y
z.get()
Out[34]:
In [35]:
z = x == y + 20
z.get()
Out[35]:
You fit perform max operations
In [36]:
x = torch.tensor([2, 3, 4, 1]).share(bob,alice, crypto_provider=crypto_provider)
x.max().get()
Out[36]:
In [37]:
x = torch.tensor([[2, 3], [4, 1]]).share(bob,alice, crypto_provider=crypto_provider)
max_values, max_ids = x.max(dim=0)
max_values.get()
Out[37]:
Clap for una sef as you don finish this notebook tutorial! If you enjoy am and you wan join the movement towards privacy preserving, decentralized ownership of AI and the AI supply chain (data), follow the steps wey dey below.
The easiset way to helep our community na to star the GitHub repos! This go helep raise awareness of the tools we dey build.
To follow up bumper to bumper on how latest advancements, join our community! You can do so by filling out the form at http://slack.openmined.org
The best way to contribute to our community na to become code contributor! You fit go to PySyft GitHub Issues page and filter for "Projects". E go show you all the top level Tickets giving an overview of what projects you fit join! If you no wan join any project, but you wan code small, you fit look for more "one off" mini-projects by searching for GitHub issues marked "good first issue"
If you no get time to contribute to our codebase, but still like to lend support, you fit be a Backer on our Open Collective. All donations wey we get na for our web hosting and other community expenses such as hackathons and meetups! meetups!
In [ ]: